package com.tiger.distributelock;

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.apache.zookeeper.proto.WatcherEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.TreeSet;
import java.util.concurrent.CountDownLatch;

//@Component
public class ZooKeeperDistributeLock implements Lock {
    private static final Logger LOG = LoggerFactory.getLogger(ZooKeeperDistributeLock.class);

    private static final String ROOT = "/lock";

    @Autowired
    private ZooKeeper zooKeeper;

    private ThreadLocal<String> id = new ThreadLocal<>();


    @PostConstruct
    public void init() {
        try {
            Stat exists = zooKeeper.exists(ROOT, false);
            if (exists == null) {
                zooKeeper.create(ROOT, "locks".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
                LOG.info("create root node");
            }
        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    @Override
    public boolean lock(String resource) {
        try {
            // 创建临时节点
            zooKeeper.create(ROOT + "/" + resource, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
            List<String> children = zooKeeper.getChildren(ROOT, false);
            TreeSet<String> sortSet = new TreeSet<>();
            children.forEach(node -> sortSet.add(node));
            String first = sortSet.first();
            String lower = sortSet.lower(first);
            // 获取到了锁
            if (first.equals(lower)) {
                return true;
            }
            // 为获取到锁
            CountDownLatch countDownLatch = new CountDownLatch(1);
            Stat stat = zooKeeper.exists(first, new LockWatcher(countDownLatch));
            if (stat != null) { //如果不为空，则一直等待
                countDownLatch.wait();
            }
        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public boolean lock(String resource, long expireTime) {



        return false;
    }

    @Override
    public void unlock(String resource) {


    }

    class LockWatcher implements Watcher {
        private CountDownLatch countDownLatch;


        public LockWatcher(CountDownLatch countDownLatch) {
            this.countDownLatch = countDownLatch;
        }


        @Override
        public void process(WatchedEvent watchedEvent) {
            if (watchedEvent.getType() == Event.EventType.NodeDeleted) {
                countDownLatch.countDown();
            }
        }
    }
}
